# -*- coding: utf-8 -*-
import logging
import requests

from common.mch.model import *
from common.withdraw.model import *
from common.mch import db as mch_db
from common.withdraw import db as trans_db

from common.mch import handler as mch_handler
from common.utils import telegram
from common.utils import tz
from common.utils import exceptions as err
from common.utils.weight_sample import weight_sample


_LOGGER = logging.getLogger(__name__)


def _choose_chn(available_channels):
    # choose one
    candidates = []
    for chn in available_channels:
        candidates.append(chn)
    if not candidates:
        raise err.PermissionError(u'mch chn not available')
    # add weight
    c_dict = dict([(i, c.weight) for i, c in enumerate(candidates)])
    chosed_index = weight_sample(c_dict.keys(), c_dict, 1).next()
    return candidates[chosed_index] 


# justpay机器人
CHAT_ID_TG_FINANCE_WARNING_GROUP = -1001331494801


def create_withdraw(charge_req):
    # check mch valid
    mch_id = charge_req['mch_id']
    service_conf = mch_db.get_mch_chn(mch_id, 'withdraw_alipay')
    if not service_conf:
        raise err.PermissionError(u'mch id not auth')
    channel_list = service_conf.chns.split(',')
    available_channels = trans_db.get_channels_in_ids(channel_list)
    if not available_channels:
        telegram.send_text_msg_tele(CHAT_ID_TG_FINANCE_WARNING_GROUP, u'没有可用支付宝下分通道')
        raise err.PermissionError(u'mch chn is empty')
    # create pay order
    withdraw_order = trans_db.create_order(charge_req)
    return {
        'order_id': withdraw_order.id
    }


def get_order_by_mch(mch_id, out_trade_no):
    order = trans_db.get_order_by_mch(mch_id, out_trade_no)
    return {
        'order_id': order.id,
        'out_trade_no': order.out_trade_no,
        'total_fee': order.total_fee,
        'status': order.status,
        'payee_no': order.payee_no,
        'payee_real_name': order.payee_real_name,
        'withdraw_at': tz.utc_to_local_str(order.withdraw_at) if order.withdraw_at else None,
    }


def construct_notify_data(order):
    data = {
        'trade_no': order.id,
        'mch_id': order.mch_id,
        'out_trade_no': order.out_trade_no,
        'order_result': order.status,
        'total_fee': float(order.total_fee),
        'extend': order.extend or '',
        'extra': order.extra or '',
    }
    sign = mch_handler.generate_sign(order.mch_id, data)
    data.update({'sign': sign})
    return data


def notify_mch(order_id):
    order = trans_db.get_order(order_id)
    if order.notify_status == NOTIFY_STATUS.SUCC:
        _LOGGER.warn('notify_mch, withdraw[%s] has been notified succ, notify again!',
            order.id)
    notify_url = order.notify_url
    # construct post data
    data = construct_notify_data(order)
    try:
        res = requests.post(notify_url, data=data, timeout=5)
        if res.text == 'success':
            _LOGGER.info('async notify_mch[%s] succ for withdraw order %s',
                order.mch_id, order.id)
            order = trans_db.add_notify_success(order.id)
            return True, order
        else:
            _LOGGER.info('async notify_mch[%s] fail for withdraw order %s, notify response %s',
                order.mch_id, order.id, res.text)
    except Exception as e:
        _LOGGER.exception('async notify_mch[%s] exception for withdraw order %s',
            order.mch_id, order.id)
    order = trans_db.add_notify_fail(order.id)
    return False, order


def get_vaild_channels_by_mch(mch_id):
    channels = trans_db.get_channels_by_mch_id(mch_id)
    ids = []
    for c in channels:
        ids.append(c.id)
    return ids